package com.heima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.admin.mapper.AdChannelMapper;
import com.heima.admin.mapper.AdSensitiveMapper;
import com.heima.admin.service.KakfaCheckArticleService;
import com.heima.common.aliyun.GreeTextScan;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.exception.CreateProjectException;
import com.heima.feigns.article.ApAuthorFeign;
import com.heima.feigns.wemedia.WmUserFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.EmptyUtil;
import com.heima.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class KakfaCheckArticleServiceImpl implements KakfaCheckArticleService {
    //远程调用接口方法 getById(通过新闻ID查询新闻)
    @Autowired
    WmUserFeign wmNewsFeign;
    @Value("${file.oss.web-site}")
    String webSite;
    @Autowired
    AdSensitiveMapper adSensitiveMapper;
    @Autowired
    GreenImageScan greenImageScan;
    @Autowired
    GreeTextScan greeTextScan;
    @Autowired
    ApAuthorFeign apArticleFeign;
    @Autowired
    AdChannelMapper adChannelMapper;

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void CheckArticleByWmNewsId(Integer id) {
        if(id==null){
            log.error("传入的ID为空");
            CreateProjectException.exec(AppHttpCodeEnum.PARAM_INVALID);
            return;
        }
        WmNews wmNews = wmNewsFeign.findById(id);
        if(EmptyUtil.isNullOrEmpty(wmNews)){
            log.error("查询不到该文章");
            CreateProjectException.exec(AppHttpCodeEnum.DATA_NOT_EXIST);
            return;
        }
        //判断 文章状态是否是4（已人工审核成功）或者 8（已审核成功） 并且 定时上传时间小于当前的时间
        if((wmNews.getStatus().equals(WmNews.Status.ADMIN_SUCCESS.getCode())||wmNews.getStatus().equals(WmNews.Status.SUCCESS.getCode()))
                && wmNews.getPublishTime().getTime() <= System.currentTimeMillis()){
            //保存数据
            saveArticle(wmNews);
            return;
        }
        //如果文章 状态=1（待审核状态）
        if(wmNews.getStatus().equals(WmNews.Status.SUBMIT.getCode())){
            //开启审核
            // 1 文章内容进行处理 方便进行审核
            Map<String,Object> map =  parseWmNews(wmNews);
            if(EmptyUtil.isNullOrEmpty(map)){
                CreateProjectException.exec(AppHttpCodeEnum.CONTENT_IS_NULL);
            }

            // 2 审核文章内容是否有关键字
            //TODO 判断redis中是否有关键词集合 储存 如果有就从redis中获取  如果没有就从数据库中查询并放入redis
            List<String> sensitives = adSensitiveMapper.querySensitiveList();
            String content = (String) map.get("content");
            SensitiveWordUtil.initMap(sensitives);
            Map<String, Integer> sensitiveCheckMap = SensitiveWordUtil.matchWords(content);
            if(sensitiveCheckMap.size() > 0){
                updateWmNews(wmNews,(short)2,"文章中包含了敏感词:"+sensitiveCheckMap);
                return;
            }
            List<String> images = (List<String>) map.get("images");
            // 3 阿里云审核图片是否违规            // 4 阿里云审核内容是否违规
            boolean aliyunFlag = handleAliyunScan(content, images, wmNews);
            if(!aliyunFlag){
                return;
            }
            // 5 修改 文章三表
            ResponseResult result = saveArticle(wmNews);
            if(result.getData() == null || !result.getCode().equals(0)){
                throw new RuntimeException("文章审核失败");
            }
            Long data = (Long) result.getData();
            //修改自媒体文章状态，状态为9  审核通过
            wmNews.setArticleId(data);
            updateWmNews(wmNews,(short) 9,"文章审核通过");
        }
    }

    /**
     *
     * @param wmNews 传入文章保存格式远程调用并返回
     * @return ResponseResult
     */
    private ResponseResult saveArticle(WmNews wmNews){
        ArticleDto articleDto = new ArticleDto();
        if(wmNews.getArticleId()!=null){
            articleDto.setId(Long.valueOf( wmNews.getArticleId()));
        }
        BeanUtils.copyProperties(wmNews,articleDto);
        //设置创建时间
        articleDto.setLayout(wmNews.getType());
        articleDto.setCreatedTime(new Date());
        //设置通道信息
        AdChannel adChannel = adChannelMapper.selectOne(Wrappers.<AdChannel>lambdaQuery().eq(AdChannel::getId, wmNews.getChannelId()));
        if(adChannel != null){
            articleDto.setChannelId(adChannel.getId());
            articleDto.setChannelName(adChannel.getName());
        }
        //设置作者信息
        WmUser wmUser = wmNewsFeign.findWmUserById(wmNews.getUserId());
        if(wmUser!=null){
            articleDto.setAuthorName(wmUser.getName());
        }
        // 文章内容
        articleDto.setContent(wmNews.getContent());
        return apArticleFeign.saveArticle(articleDto);
    }


    /**
     * 阿里云解析文章内容和图片信息
     * @param context
     * @param images
     * @param wmNews
     * @return
     */
    private boolean handleAliyunScan(String context,List<String> images,WmNews wmNews){
        if(images==null||images.size()==0||StringUtils.isBlank(context)){
            return true;
        }
        try {
            Map map = greenImageScan.imageUrlScan(images);
            if(map.get("suggestion").equals("block")){
                updateWmNews(wmNews, (short) 2, "图片审核失败，请更换图片");
                return false;
            }
            if(map.get("suggestion").equals("review")){
                updateWmNews(wmNews, (short) 3, "阿里云审核失败，转入人工审核");
                return false;
            }
            Map contentMap = greeTextScan.greeTextScan(context);
            if(contentMap.get("suggestion").equals("block")){
                updateWmNews(wmNews, (short) 2, "文章审核失败，请检查文章");
                return false;
            }
            if(contentMap.get("suggestion").equals("review")){
                updateWmNews(wmNews, (short) 3, "阿里云审核失败，转入人工审核");
                return false;
            }
        } catch (Exception e) {
            updateWmNews(wmNews, (short) 3, "阿里云审核失败，转入人工审核");
            return false;
        }
        return true;
    }

    /**
     * 修改wmNews 文章
     * @param wmNews 文章实体类
     * @param type 文章类型
     * @param reason 注释
     */
    private void updateWmNews(WmNews wmNews, short type, String reason) {
        wmNews.setStatus(type);
        wmNews.setReason(reason);
        ResponseResult<Boolean> flag = wmNewsFeign.updateWmNews(wmNews);
        if(!flag.getData()){
            CreateProjectException.exec(AppHttpCodeEnum.UPDATE_ERROR);
        }
    }

    /**
     * 格式化文章
     * @param wmNews
     * @return 返回一个Map 分别储存图片集合 文章内容 用作阿里云的鉴定操作
     */
    private Map<String, Object> parseWmNews(WmNews wmNews) {
        String content = wmNews.getContent();
        if(StringUtils.isEmpty(content)){
            return null;
        }
        StringBuilder sb = new StringBuilder();
        ArrayList<String> images = new ArrayList<>();
        List<Map> contents = JSON.parseArray(content, Map.class);
        for (Map<String,String> con : contents) {
            if(con.get("type").equals("text")){
                sb.append(con.get("value"));
                sb.append("__z_");
            }
            if(con.get("type").equals("image")){
                images.add(con.get("value"));
            }
        }
        if(wmNews.getImages() != null){
            List<String> imges = Arrays.asList(wmNews.getImages());
            for (String imge : imges) {
                images.add(webSite+""+imge);
            }
        }
        List<String> collect = images.stream().distinct().collect(Collectors.toList());
        HashMap<String, Object> map = new HashMap<>();
        map.put("content",sb.toString());
        map.put("images",collect);
        return map;
    }
}
